package com.google.zxing.view;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.Toast;

import com.google.zxing.ResultPoint;
import com.google.zxing.camera.CameraManager;
import com.google.zxing.common.FlashLightManager;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import barcan.flutter.io.barscan.R;

import static android.view.Gravity.CENTER;


/**
 * This view is overlaid on top of the camera preview. It adds the viewfinder
 * rectangle and partial transparency outside it, as well as the laser scanner
 * animation and result points.
 * <p>
 * <br/>
 * <br/>
 * 该视图是覆盖在相机的预览视图之上的一层视图。扫描区构成原理，其实是在预览视图上画四块遮罩层，
 * 中间留下的部分保持透明，并画上一条激光线，实际上该线条就是展示而已，与扫描功能没有任何关系。
 *
 * @author dswitkin@google.com (Daniel Switkin)
 */
public final class ViewfinderView extends View {
    public static  String TRADE_MARK_TEXT = "轻触点亮";
    /**
     * 刷新界面的时间
     */
    private static final long ANIMATION_DELAY = 10L;
    private static final int OPAQUE = 0xFF;
    /**
     * 中间那条线每次刷新移动的距离
     */
    private static final int SPEEN_DISTANCE = 10;
    private static final int MAX_RESULT_POINTS = 20;
    /**
     * 扫描框中的中间线的宽度
     */
    private static int MIDDLE_LINE_WIDTH;
    /**
     * 扫描框中的中间线的与扫描框左右的间隙
     */
    private static int MIDDLE_LINE_PADDING;

    private boolean isFlashOn = false;
    /**
     * 遮掩层的颜色
     */
    private final int maskColor;
    private final int resultPointColor;
    //扫描线颜色
    private final int laserColor;
    /**
     * 第一次绘制控件
     */
    boolean isFirst = true;
    private int CORNER_PADDING;
    /**
     * 画笔对象的引用
     */
    private Paint paint;
    /**
     * 中间滑动线的最顶端位置
     */
    private int slideTop;
    /**
     * 中间滑动线的最底端位置
     */
    private int slideBottom;
    private Bitmap resultBitmap;
    private List<ResultPoint> possibleResultPoints;
    private List<ResultPoint> lastPossibleResultPoints;
    private View tipView;
    private View errorView;
    private CameraManager cameraManager;
    private  String language;
    boolean isBarCode = false;
    private static final int CORNER_RECT_WIDTH = 8;  //扫描区边角的宽
    private static final int CORNER_RECT_HEIGHT = 40; //扫描区边角的高
    private Bitmap offBitmap;
    private Bitmap onBitmap;
    RectF lineRect = new RectF();
    private Rect mSrcRect;
    private Rect mDestRect;
    private float mTradeMarkLeft;
    private float mTradeMarkTop;

    // This constructor is used when the class is built from an XML resource.
    public ViewfinderView(Context context, AttributeSet attrs) {
        super(context, attrs);

        CORNER_PADDING = -5;
        MIDDLE_LINE_PADDING = dip2px(context, 0.0F);
        MIDDLE_LINE_WIDTH = dip2px(context, 1.0F);

        paint = new Paint(Paint.ANTI_ALIAS_FLAG); // 开启反锯齿

        Resources resources = getResources();
        maskColor = Color.argb(204, 0, 0, 0); // 遮掩层颜色
        laserColor = resources.getColor(R.color.scan_line);
        resultPointColor = resources.getColor(R.color.scan_possible_result_points);
        possibleResultPoints = new ArrayList<ResultPoint>(5);
        lastPossibleResultPoints = null;
        if (offBitmap == null) {
            offBitmap = getResIcon(getResources(), R.drawable.flash_off);
        }
        if (onBitmap == null) {
            onBitmap = getResIcon(getResources(), R.drawable.flash_on);
        }
    }

    private Bitmap getResIcon(Resources res, int resId) {
        Drawable icon = res.getDrawable(resId);
        if (icon instanceof BitmapDrawable) {
            BitmapDrawable bd = (BitmapDrawable) icon;
            return bd.getBitmap();
        } else {
            return null;
        }
    }

    private void touch() {
        try {
            //    FlashLightManager.turnLightOff(cameraManager.getCamera());
            //   FlashLightManager.turnLightOn(cameraManager.getCamera());

//            boolean isSuccess = CameraManager.get().setFlashLight(!isFlashOn);
//            if (!isSuccess) {
//                Toast.makeText(getContext(), "暂时无法开启闪光灯", Toast.LENGTH_SHORT).show();
//                return;
//            }
            if (isFlashOn) {
                // 关闭闪光灯
                // btnFlash.setImageResource(R.drawable.flash_off);
                FlashLightManager.turnLightOff(cameraManager.getCamera());
                isFlashOn = false;
            } else {
                // 开启闪光灯
                // btnFlash.setImageResource(R.drawable.flash_on);
                FlashLightManager.turnLightOn(cameraManager.getCamera());
                isFlashOn = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float rawX = event.getRawX();
        float rawY = event.getRawY();
        float x = event.getX();
        float y = event.getY();
        if ((mTradeMarkTop - 150) <= y && (mTradeMarkTop + 150) >= y) {
            if ((mTradeMarkLeft - 150) <= x && (mTradeMarkLeft + 150) >= x) {
                touch();
            }
        }

        return super.onTouchEvent(event);
    }

    public void setCameraManager(CameraManager cameraManager,String language) {
        this.cameraManager = cameraManager;
        this.language=language;
        if(this.language!=null && "en".equals(language)){
            TRADE_MARK_TEXT="Touch";
        }
    }

    public void setTipView(View tipView) {
        this.tipView = tipView;
    }

    public void setErrorView(View errorView) {
        this.errorView = errorView;
    }

    public void setBarCode(Boolean barCode) {
        this.isBarCode = barCode;
    }

    public void setBarCodeRecy(Boolean barCode) {
        this.isFirst = true;
        this.isBarCode = barCode;
        if (cameraManager != null) {
            cameraManager.framingRect();
            cameraManager.framingRectInPreview();
        }
        requestLayout();
        invalidate();
    }

    @Override
    public void onDraw(Canvas canvas) {
        if (cameraManager == null) {
            return; // not ready yet, early draw before done configuring
        }
        Rect frame = cameraManager.getFramingRect(isBarCode);

        if (frame == null) {
            if (errorView != null) {
                FrameLayout.LayoutParams ll = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
                ll.gravity = CENTER;
                errorView.setLayoutParams(ll);
                errorView.setVisibility(VISIBLE);
                tipView.setVisibility(GONE);
            }
            return;
        }

        // 绘制遮掩层
        drawCover(canvas, frame);

        if (resultBitmap != null) { // 绘制扫描结果的图
            // Draw the opaque result bitmap over the scanning rectangle
            paint.setAlpha(0xA0);
            canvas.drawBitmap(resultBitmap, null, frame, paint);
        } else {
            drawFrame(canvas, frame);
            // 画扫描框边上的角
            drawRectEdges(canvas, frame);

            // 绘制扫描线
            drawScanningLine(canvas, frame);

            paint.setColor(laserColor);
            paint.setDither(true);//防抖动
            paint.setFilterBitmap(true);
            float tradeMarkLeft ;
            float tradeMarkTop ;
            paint.setTextSize(36f);
            if (frame != null) {
                float ss = frame.width() / 2;
                tradeMarkLeft = frame.left + ss-50;
                tradeMarkTop = frame.bottom - 20;

            } else {
                tradeMarkTop = 10;
                tradeMarkLeft = getHeight() - 50;
            }
            if(language!=null && "en".equals(language)){
                tradeMarkLeft=tradeMarkLeft+10;
            }
            canvas.drawText(TRADE_MARK_TEXT, tradeMarkLeft, tradeMarkTop, paint);

             tradeMarkLeft = frame.left + frame.width() / 2;
             tradeMarkTop = frame.bottom - 100;

            if (mSrcRect == null) {
                mSrcRect = new Rect(0, 0, 131, 200);
            }
            if (mDestRect == null) {
                mTradeMarkLeft = tradeMarkLeft;
                mTradeMarkTop = tradeMarkTop;
                mDestRect = new Rect((int) tradeMarkLeft, (int) tradeMarkTop, (int) tradeMarkLeft + 30, (int) tradeMarkTop + 40);
            }
            if (offBitmap != null && !isFlashOn) {
                canvas.drawBitmap(offBitmap, mSrcRect, mDestRect, paint);
            } else if (onBitmap != null && isFlashOn) {
                canvas.drawBitmap(onBitmap, mSrcRect, mDestRect, paint);
            }

            List<ResultPoint> currentPossible = possibleResultPoints;
            Collection<ResultPoint> currentLast = lastPossibleResultPoints;
            if (currentPossible.isEmpty()) {
                lastPossibleResultPoints = null;
            } else {
                possibleResultPoints = new ArrayList<ResultPoint>(5);
                lastPossibleResultPoints = currentPossible;
                paint.setAlpha(OPAQUE);
                paint.setColor(resultPointColor);
                for (ResultPoint point : currentPossible) {
                    canvas.drawCircle(frame.left + point.getX(), frame.top
                            + point.getY(), 6.0f, paint);
                }
            }
            if (currentLast != null) {
                paint.setAlpha(OPAQUE / 2);
                paint.setColor(resultPointColor);
                for (ResultPoint point : currentLast) {
                    canvas.drawCircle(frame.left + point.getX(), frame.top
                            + point.getY(), 3.0f, paint);
                }
            }

            // 只刷新扫描框的内容，其他地方不刷新
            postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top,
                    frame.right, frame.bottom);

        }
    }

    public static int scannerStart = 0;
    public static int scannerEnd = 0;
    private static final int SCANNER_LINE_MOVE_DISTANCE = 5;  //扫描线移动距离
    private static final int SCANNER_LINE_HEIGHT = 10;  //扫描线宽度

    public int shadeColor(int color) {
        String hax = Integer.toHexString(color);
        String result = "20" + hax.substring(2);
        return Integer.valueOf(result, 16);
    }

    /**
     * 绘制扫描线
     *
     * @param canvas
     * @param frame  扫描框
     */
    private void drawScanningLine(Canvas canvas, Rect frame) {
        // 初始化中间线滑动的最上边和最下边
        if (isFirst) {
            isFirst = false;
            slideTop = frame.top;
            slideBottom = frame.bottom;
        }
        // 绘制中间的线,每次刷新界面，中间的线往下移动SPEEN_DISTANCE
        slideTop += SPEEN_DISTANCE;
        if (slideTop >= slideBottom) {
            slideTop = frame.top;
        }
        // 从图片资源画扫描线
        paint.setColor(laserColor);
        lineRect.left = frame.left + MIDDLE_LINE_PADDING;
        lineRect.right = frame.right - MIDDLE_LINE_PADDING;
        lineRect.top = slideTop;
        lineRect.bottom = (slideTop + MIDDLE_LINE_WIDTH);
        canvas.drawOval(lineRect, paint);
    }

    /**
     * 绘制遮掩层
     *
     * @param canvas
     * @param frame
     */
    private void drawCover(Canvas canvas, Rect frame) {
        // 获取屏幕的宽和高
        int width = canvas.getWidth();
        int height = canvas.getHeight();

        // Draw the exterior (i.e. outside the framing rect) darkened
        paint.setColor(maskColor);

        // 画出扫描框外面的阴影部分，共四个部分，扫描框的上面到屏幕上面，扫描框的下面到屏幕下面
        // 扫描框的左边面到屏幕左边，扫描框的右边到屏幕右边
        canvas.drawRect(0, 0, width, frame.top, paint);
        canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
        canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1,
                paint);
        canvas.drawRect(0, frame.bottom + 1, width, height, paint);
    }

    //绘制边角
    private void drawCorner(Canvas canvas, Rect frame) {
        paint.setColor(Color.WHITE);
        //左上
        canvas.drawRect(frame.left, frame.top, frame.left + CORNER_RECT_WIDTH, frame.top + CORNER_RECT_HEIGHT, paint);
        canvas.drawRect(frame.left, frame.top, frame.left + CORNER_RECT_HEIGHT, frame.top + CORNER_RECT_WIDTH, paint);
        //右上
        canvas.drawRect(frame.right - CORNER_RECT_WIDTH, frame.top, frame.right, frame.top + CORNER_RECT_HEIGHT, paint);
        canvas.drawRect(frame.right - CORNER_RECT_HEIGHT, frame.top, frame.right, frame.top + CORNER_RECT_WIDTH, paint);
        //左下
        canvas.drawRect(frame.left, frame.bottom - CORNER_RECT_WIDTH, frame.left + CORNER_RECT_HEIGHT, frame.bottom, paint);
        canvas.drawRect(frame.left, frame.bottom - CORNER_RECT_HEIGHT, frame.left + CORNER_RECT_WIDTH, frame.bottom, paint);
        //右下
        canvas.drawRect(frame.right - CORNER_RECT_WIDTH, frame.bottom - CORNER_RECT_HEIGHT, frame.right, frame.bottom, paint);
        canvas.drawRect(frame.right - CORNER_RECT_HEIGHT, frame.bottom - CORNER_RECT_WIDTH, frame.right, frame.bottom, paint);
    }

    /**
     * 描绘方形的四个角
     *
     * @param canvas
     * @param frame
     */
    private void drawRectEdges(Canvas canvas, Rect frame) {
        paint.setColor(laserColor);
        //左上
        canvas.drawRect(frame.left, frame.top, frame.left + CORNER_RECT_WIDTH, frame.top + CORNER_RECT_HEIGHT, paint);
        canvas.drawRect(frame.left, frame.top, frame.left + CORNER_RECT_HEIGHT, frame.top + CORNER_RECT_WIDTH, paint);
        //右上
        canvas.drawRect(frame.right - CORNER_RECT_WIDTH, frame.top, frame.right, frame.top + CORNER_RECT_HEIGHT, paint);
        canvas.drawRect(frame.right - CORNER_RECT_HEIGHT, frame.top, frame.right, frame.top + CORNER_RECT_WIDTH, paint);
        //左下
        canvas.drawRect(frame.left, frame.bottom - CORNER_RECT_WIDTH, frame.left + CORNER_RECT_HEIGHT, frame.bottom, paint);
        canvas.drawRect(frame.left, frame.bottom - CORNER_RECT_HEIGHT, frame.left + CORNER_RECT_WIDTH, frame.bottom, paint);
        //右下
        canvas.drawRect(frame.right - CORNER_RECT_WIDTH, frame.bottom - CORNER_RECT_HEIGHT, frame.right, frame.bottom, paint);
        canvas.drawRect(frame.right - CORNER_RECT_HEIGHT, frame.bottom - CORNER_RECT_WIDTH, frame.right, frame.bottom, paint);

        if (tipView != null) {
            FrameLayout.LayoutParams ll =
                    (FrameLayout.LayoutParams) tipView.getLayoutParams();
            ll.setMargins(0, frame.bottom + 10, 0, 0);
            tipView.setLayoutParams(ll);
            tipView.setVisibility(VISIBLE);
            errorView.setVisibility(GONE);
        }
    }

    public void drawViewfinder() {
        Bitmap resultBitmap = this.resultBitmap;
        this.resultBitmap = null;
        if (resultBitmap != null) {
            resultBitmap.recycle();
        }
        invalidate();
    }

    /**
     * Draw a bitmap with the result points highlighted instead of the live
     * scanning display.
     *
     * @param barcode An image of the decoded barcode.
     */
    public void drawResultBitmap(Bitmap barcode) {
        resultBitmap = barcode;
        invalidate();
    }

    public void addPossibleResultPoint(ResultPoint point) {
        List<ResultPoint> points = possibleResultPoints;
        synchronized (points) {
            points.add(point);
            int size = points.size();
            if (size > MAX_RESULT_POINTS) {
                // trim it
                points.subList(0, size - MAX_RESULT_POINTS / 2).clear();
            }
        }
    }

    // 绘制扫描区边框 Draw a two pixel solid black border inside the framing rect
    private void drawFrame(Canvas canvas, Rect frame) {
        paint.setColor(Color.WHITE);
        canvas.drawRect(frame.left, frame.top, frame.right + 1, frame.top + 2, paint);
        canvas.drawRect(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1, paint);
        canvas.drawRect(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1, paint);
        canvas.drawRect(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1, paint);
    }

    /**
     * dp转px
     *
     * @param context
     * @param dipValue
     * @return
     */
    public int dip2px(Context context, float dipValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }

    @Override
    protected void onDetachedFromWindow() {
        offBitmap = null;
        onBitmap = null;
        resultBitmap = null;
        super.onDetachedFromWindow();
    }
}
